package org.jawa.exam.question;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.jawa.admin.util.Page;
import org.jawa.core.cache.Cache;
import org.jawa.core.cache.CacheFactory;
import org.jawa.core.database.DbConnectionManager;
import org.jawa.core.exception.NotFoundException;
import org.jawa.exam.model.Question;
import org.jawa.exam.model.QuestionOption;
import org.jawa.exam.model.QuestionSort;
import org.jawa.jdbc.JdbcUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class QuestionManager {
    private static final Logger Log = LoggerFactory
	    .getLogger(QuestionManager.class);

    /**
     * 根据试题类型查询的SQL.
     */
    private static final String QUESTION_COUNT = "SELECT count(*) FROM QUESTION WHERE question_type=?";

    // 试题缓存
    private Cache<Long, Question> questionCache;

    // 试题分类缓存
    private Cache<Long, QuestionSort> questionSortCache;

    // 单一实例.
    private static class QuestionManagerContainer {
	private static QuestionManager instance = new QuestionManager();
    }

    public static QuestionManager getInstance() {
	return QuestionManagerContainer.instance;
    }

    private QuestionManager() {
	questionCache = CacheFactory.createCache("question");
	questionCache = CacheFactory.createCache("questionSort");
    }

    /**
     * 创建试题信息.
     * 
     * @param Question
     *            试题信息.
     * @return 创建好的试题信息实例.
     * @throws Exception
     *             创建试题信息异常.
     */
    public Question createQuestion(Question question,
	    List<QuestionOption> questionOptions) throws Exception {
	Connection con = null;
	boolean abortTransaction = false;
	try {
	    con = DbConnectionManager.getTransactionConnection();
	    for (Iterator iterator = questionOptions.iterator(); iterator
		    .hasNext();) {
		QuestionOption questionOption = (QuestionOption) iterator
			.next();
		JdbcUtils.insertTableFromBean(con, "QUESTION_OPTION",
			questionOption, "CachedSize");
	    }
	    JdbcUtils.insertTableFromBean(con, "QUESTION", question,
		    "CachedSize");
	} catch (Exception e) {
	    abortTransaction = true;
	    Log.error("将试题存入数据库时发生错误!", e);
	    throw e;
	} finally {
	    DbConnectionManager.closeTransactionConnection(con,
		    abortTransaction);
	}
	questionCache.put(question.getQuestionId(), question);
	return question;
    }

    /**
     * 根据查询条件返回系统中的试题.
     * 
     * @param startIndex
     * @param numResults
     * @return
     * @throws
     */
    public List<Question> getQuestions(Page page) {
	List questions = new ArrayList();
	StringBuffer sql = new StringBuffer();
	sql.append("SELECT * FROM QUESTION WHERE 1=1 ");
	try {
	    questions = JdbcUtils.queryToBeanList(Question.class,
		    sql.toString());
	    page.setTotalCount(JdbcUtils.countSqlRowNumber(sql.toString()));
	} catch (SQLException e) {
	    Log.error("查询试卷信息时发生错误!", e);
	}
	return questions;
    }

    /**
     * 根据查询条件返回系统中试题选项.
     * 
     * @param startIndex
     * @param numResults
     * @return
     * @throws
     */
    public List<QuestionOption> getQuestionOptions(Long questionId) {
	List questions = new ArrayList();
	StringBuffer sql = new StringBuffer();
	sql.append("SELECT * FROM QUESTION_OPTION WHERE 1=1 AND QUESTIONID = ? ");
	try {
	    questions = JdbcUtils.queryToBeanList(QuestionOption.class,
		    sql.toString(),questionId);
	} catch (SQLException e) {
	    Log.error("查询试题选项信息时发生错误!", e);
	}
	return questions;
    }
    /**
     * 返回指定 brId 的部门.
     * 
     * @param userId
     *            部门的 brId .
     * @return br_Id 等于 <tt>brId</tt> 的部门.
     * @throws NotFoundException
     *             部门没有找到.
     */
    public Question getQuestion(Long questionId) throws NotFoundException {
	if (questionId == null) {
	    throw new NotFoundException("questionId cannot be null");
	}

	Question question = questionCache.get(questionId);
	if (question == null) {
	    synchronized (questionCache) {
		question = questionCache.get(questionId);
		if (question == null) {
		    question = loadQuestionById(questionId);
		    // 放入部门缓存
		    questionCache.put(questionId, question);
		}
	    }
	}
	return question;
    }

    /**
     * 根据 questionId从数据库加载试题。
     * 
     * @param questionId
     *            questionId
     * @return 试题.
     * 
     * @throws 假如试题没有找到抛出
     *             NotFoundException.
     * 
     */
    public Question loadQuestionById(Long questionId) throws NotFoundException {
	Question question = null;
	try {
	    question = JdbcUtils.queryToBean(Question.class,
		    "SELECT * FROM QUESTION WHERE questionId = ? ", questionId);
	    return question;
	} catch (Exception e) {
	    Log.error("查询部门信息时出错", e);
	    throw new NotFoundException();
	}
    }

    /**
     * 返回所有的试题分类
     * 
     * @Title: QuestionManager
     * @Description: TODO
     * @param @return
     * @throws
     */
    public List<QuestionSort> getQuestionSorts() {
	List sorts = new ArrayList();
	StringBuffer sql = new StringBuffer();
	sql.append("SELECT * FROM QUESTIONSORT WHERE 1=1 ");
	try {
	    sorts = JdbcUtils.queryToBeanList(QuestionSort.class,
		    sql.toString());
	} catch (SQLException e) {
	    Log.error("查询试题分类信息时发生错误!", e);
	}

	return sorts;
    }

    /**
     * 返回指定的试题分类.
     * 
     * @param questionSortId
     *            试题分类编码 .
     * @return 试题分类.
     * @throws NotFoundException
     *             没有找到.
     */
    public QuestionSort getQuestionSort(Long questionSortId)
	    throws NotFoundException {
	if (questionSortId == null) {
	    throw new NotFoundException("questionSortId cannot be null");
	}

	QuestionSort questionSort = questionSortCache.get(questionSortId);
	if (questionSort == null) {
	    synchronized (questionSortCache) {
		questionSort = questionSortCache.get(questionSortId);
		if (questionSort == null) {
		    questionSort = loadQuestionSortById(questionSortId);
		    // 放入部门缓存
		    questionSortCache.put(questionSortId, questionSort);
		}
	    }
	}
	return questionSort;
    }

    /**
     * 根据 questionSortId从数据库加载试题分类。
     * 
     * @param questionId
     *            questionId
     * @return 试题分类编码.
     * 
     * @throws 假如没有找到抛出
     *             NotFoundException.
     * 
     */
    private QuestionSort loadQuestionSortById(Long questionSortId)
	    throws NotFoundException {
	QuestionSort questionSort = null;
	try {
	    questionSort = JdbcUtils.queryToBean(QuestionSort.class,
		    "SELECT * FROM QUESTIONSORT WHERE sortId = ? ",
		    questionSortId);
	    return questionSort;
	} catch (Exception e) {
	    Log.error("查询试题分类时出错", e);
	    throw new NotFoundException();
	}
    }

    /**
     * 根据试题类型获取当前类型下试题总数
     * 
     * @param papaerType
     *            试题类型
     * @return 返回该类型下试题总数
     */
    public int getQuestionCount(String questionType) {
	int count = 0;
	Connection con = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	try {
	    con = DbConnectionManager.getConnection();
	    pstmt = con.prepareStatement(QUESTION_COUNT);
	    pstmt.setString(0, questionType);
	    rs = pstmt.executeQuery();
	    if (rs.next()) {
		count = rs.getInt(1);
	    }
	} catch (SQLException e) {
	    Log.error("获取试题信息总数出错！", e);
	} finally {
	    DbConnectionManager.closeConnection(rs, pstmt, con);
	}
	return count;
    }

}
